package com.yunke.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunke.common.log.BusinessLog;
import com.yunke.common.result.YunkeResult;
import com.yunke.common.security.YunkeSecurityUtil;
import com.yunke.dto.user.YunkeSendSmsDto;
import com.yunke.dto.user.YunkeUserLoginDto;
import com.yunke.dto.user.YunkeUserProfileDto;
import com.yunke.dto.user.YunkeUserRegisterDto;
import com.yunke.dto.YunkeWechatLoginDto;
import com.yunke.dto.YunkeRealAuthDto;
import com.yunke.entity.YunkeUser;
import com.yunke.service.YunkeUserService;
import com.yunke.vo.user.YunkeUserCenterVo;
import com.yunke.vo.user.YunkeUserInfoVo;
import com.yunke.vo.user.YunkeUserLoginVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotBlank;

/**
 * 云科用户认证控制器
 * 
 * @author yunke
 * @since 2024-01-01
 */
@Slf4j
@RestController
@RequestMapping("/api/user")
@RequiredArgsConstructor
@Validated
@Tag(name = "用户认证", description = "用户注册、登录、认证相关接口")
public class YunkeUserController {

    private final YunkeUserService userService;

    /**
     * 发送短信验证码
     */
    @PostMapping("/sendSms")
    @Operation(summary = "发送短信验证码", description = "发送手机短信验证码")
    @BusinessLog(value = "发送短信验证码", params = "phone")
    public YunkeResult<Boolean> sendSms(@Valid @RequestBody YunkeSendSmsDto dto) {
        boolean result = userService.sendSmsCode(dto.getPhone(), dto.getType());
        return YunkeResult.success(result);
    }

    /**
     * 用户注册
     */
    @PostMapping("/register")
    @Operation(summary = "用户注册", description = "用户手机号注册")
    @BusinessLog(value = "用户注册", params = "phone")
    public YunkeResult<Boolean> register(@Valid @RequestBody YunkeUserRegisterDto dto) {
        boolean result = userService.register(dto.getPhone(), dto.getSmsCode(), 
                                            dto.getPassword(), dto.getInviteCode());
        return YunkeResult.success(result);
    }

    /**
     * 用户登录
     */
    @PostMapping("/login")
    @Operation(summary = "用户登录", description = "用户密码登录")
    @BusinessLog(value = "用户登录", params = "username")
    public YunkeResult<YunkeUserLoginVo> login(@Valid @RequestBody YunkeUserLoginDto dto) {
        YunkeUserLoginVo result = userService.login(dto.getUsername(), dto.getPassword());
        return YunkeResult.success(result);
    }

    /**
     * 短信验证码登录
     */
    @PostMapping("/smsLogin")
    @Operation(summary = "短信验证码登录", description = "手机号+验证码登录")
    @BusinessLog(value = "短信验证码登录", params = "phone")
    public YunkeResult<YunkeUserLoginVo> smsLogin(
            @Parameter(description = "手机号") @NotBlank @RequestParam String phone,
            @Parameter(description = "短信验证码") @NotBlank @RequestParam String smsCode) {
        YunkeUserLoginVo result = userService.smsLogin(phone, smsCode);
        return YunkeResult.success(result);
    }

    /**
     * 获取用户信息
     */
    @GetMapping("/info")
    @Operation(summary = "获取用户信息", description = "获取当前登录用户的详细信息")
    @BusinessLog(value = "获取用户信息")
    public YunkeResult<YunkeUserInfoVo> getUserInfo() {
        YunkeUserInfoVo result = userService.getCurrentUserInfo();
        return YunkeResult.success(result);
    }

    /**
     * 更新用户信息
     */
    @PostMapping("/update")
    @Operation(summary = "更新用户信息", description = "更新当前登录用户的基本信息")
    @BusinessLog(value = "更新用户信息")
    public YunkeResult<Boolean> updateUserInfo(@Valid @RequestBody YunkeUserInfoVo userInfo) {
        boolean result = userService.updateUserInfo(userInfo);
        return YunkeResult.success(result);
    }

    /**
     * 忘记密码
     */
    @PostMapping("/forgetPassword")
    @Operation(summary = "忘记密码", description = "通过手机号+验证码重置密码")
    @BusinessLog(value = "忘记密码", params = "phone")
    public YunkeResult<Boolean> forgetPassword(
            @Parameter(description = "手机号") @NotBlank @RequestParam String phone,
            @Parameter(description = "短信验证码") @NotBlank @RequestParam String smsCode,
            @Parameter(description = "新密码") @NotBlank @RequestParam String newPassword) {
        boolean result = userService.forgetPassword(phone, smsCode, newPassword);
        return YunkeResult.success(result);
    }

    /**
     * 修改密码
     */
    @PostMapping("/changePassword")
    @Operation(summary = "修改密码", description = "修改当前用户密码")
    @BusinessLog(value = "修改密码")
    public YunkeResult<Boolean> changePassword(
            @Parameter(description = "旧密码") @NotBlank @RequestParam String oldPassword,
            @Parameter(description = "新密码") @NotBlank @RequestParam String newPassword) {
        boolean result = userService.changePassword(oldPassword, newPassword);
        return YunkeResult.success(result);
    }

    /**
     * 退出登录
     */
    @PostMapping("/logout")
    @Operation(summary = "退出登录", description = "用户退出登录")
    @BusinessLog(value = "退出登录")
    public YunkeResult<Boolean> logout() {
        boolean result = userService.logout();
        return YunkeResult.success(result);
    }

    /**
     * 刷新Token
     */
    @PostMapping("/refreshToken")
    @Operation(summary = "刷新Token", description = "刷新用户登录Token")
    @BusinessLog(value = "刷新Token")
    public YunkeResult<String> refreshToken() {
        String newToken = userService.refreshToken();
        return YunkeResult.success(newToken);
    }

    /**
     * 绑定手机号
     */
    @PostMapping("/bindPhone")
    @Operation(summary = "绑定手机号", description = "为当前用户绑定手机号")
    @BusinessLog(value = "绑定手机号", params = "phone")
    public YunkeResult<Boolean> bindPhone(
            @Parameter(description = "手机号") @NotBlank @RequestParam String phone,
            @Parameter(description = "短信验证码") @NotBlank @RequestParam String smsCode) {
        boolean result = userService.bindPhone(phone, smsCode);
        return YunkeResult.success(result);
    }

    /**
     * 解绑手机号
     */
    @PostMapping("/unbindPhone")
    @Operation(summary = "解绑手机号", description = "解绑当前用户的手机号")
    @BusinessLog(value = "解绑手机号")
    public YunkeResult<Boolean> unbindPhone(
            @Parameter(description = "短信验证码") @NotBlank @RequestParam String smsCode) {
        boolean result = userService.unbindPhone(smsCode);
        return YunkeResult.success(result);
    }

    /**
     * 微信登录
     */
    @PostMapping("/wechatLogin")
    @Operation(summary = "微信登录", description = "微信授权码登录")
    @BusinessLog(value = "微信登录", params = "code")
    public YunkeResult<YunkeUserLoginVo> wechatLogin(@Valid @RequestBody YunkeWechatLoginDto dto) {
        YunkeUserLoginVo result = userService.wechatLoginWithResult(dto.getCode(), dto.getInviteCode());
        return YunkeResult.success(result);
    }

    /**
     * 实名认证
     */
    @PostMapping("/realAuth")
    @Operation(summary = "实名认证", description = "提交用户实名认证信息")
    @BusinessLog(value = "实名认证", params = "realName")
    public YunkeResult<Boolean> realNameAuth(@Valid @RequestBody YunkeRealAuthDto dto) {
        boolean result = userService.realNameAuth(dto.getRealName(), dto.getIdCardNumber(), 
                                                 dto.getIdCardFront(), dto.getIdCardBack());
        return YunkeResult.success(result);
    }

    // ==================== 个人中心模块接口 ====================

    /**
     * 获取个人中心首页
     */
    @GetMapping("/center")
    @Operation(summary = "获取个人中心首页", description = "获取个人中心首页信息")
    @BusinessLog(value = "获取个人中心首页")
    public YunkeResult<YunkeUserCenterVo> getUserCenter() {
        YunkeUserCenterVo result = userService.getUserCenter();
        return YunkeResult.success(result);
    }

    /**
     * 获取用户详细信息
     */
    @GetMapping("/profile")
    @Operation(summary = "获取用户详细信息", description = "获取用户详细信息")
    @BusinessLog(value = "获取用户详细信息")
    public YunkeResult<YunkeUserInfoVo> getUserProfile(
            @Parameter(description = "用户ID（为空时查询当前用户）") @RequestParam(required = false) Long userId) {
        YunkeUserInfoVo result = userService.getUserProfile(userId);
        return YunkeResult.success(result);
    }

    /**
     * 编辑个人信息
     */
    @PostMapping("/editProfile")
    @Operation(summary = "编辑个人信息", description = "编辑个人基本信息")
    @BusinessLog(value = "编辑个人信息")
    public YunkeResult<Boolean> editProfile(@Valid @RequestBody YunkeUserProfileDto dto) {
        boolean result = userService.editProfile(dto);
        return YunkeResult.success(result);
    }

    /**
     * 关注/取消关注用户
     */
    @PostMapping("/follow/{followUserId}")
    @Operation(summary = "关注用户", description = "关注或取消关注用户")
    @BusinessLog(value = "关注用户", params = "followUserId")
    public YunkeResult<Boolean> followUser(@Parameter(description = "被关注用户ID") @PathVariable Long followUserId) {
        boolean result = userService.followUser(followUserId);
        return YunkeResult.success(result);
    }

    /**
     * 获取关注列表
     */
    @GetMapping("/followList")
    @Operation(summary = "获取关注列表", description = "获取我的关注列表")
    @BusinessLog(value = "获取关注列表")
    public YunkeResult<Page<YunkeUserInfoVo>> getFollowList(
            @Parameter(description = "当前页码") @RequestParam(defaultValue = "1") Long current,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Long size) {
        Page<YunkeUserInfoVo> result = userService.getFollowList(current, size);
        return YunkeResult.success(result);
    }

    /**
     * 获取粉丝列表
     */
    @GetMapping("/fansList")
    @Operation(summary = "获取粉丝列表", description = "获取我的粉丝列表")
    @BusinessLog(value = "获取粉丝列表")
    public YunkeResult<Page<YunkeUserInfoVo>> getFansList(
            @Parameter(description = "当前页码") @RequestParam(defaultValue = "1") Long current,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Long size) {
        Page<YunkeUserInfoVo> result = userService.getFansList(current, size);
        return YunkeResult.success(result);
    }

    /**
     * 获取用户统计数据
     */
    @GetMapping("/statistics")
    @Operation(summary = "获取用户统计数据", description = "获取用户统计数据")
    @BusinessLog(value = "获取用户统计数据")
    public YunkeResult<YunkeUserCenterVo.StatisticsInfo> getUserStatistics() {
        YunkeUserCenterVo.StatisticsInfo result = userService.getUserStatistics();
        return YunkeResult.success(result);
    }

    /**
     * 获取邀请信息
     */
    @GetMapping("/inviteInfo")
    @Operation(summary = "获取邀请信息", description = "获取用户邀请信息")
    @BusinessLog(value = "获取邀请信息")
    public YunkeResult<YunkeUserCenterVo.InviteInfo> getInviteInfo() {
        YunkeUserCenterVo.InviteInfo result = userService.getInviteInfo();
        return YunkeResult.success(result);
    }

    /**
     * 查看其他用户信息
     */
    @GetMapping("/otherProfile/{userId}")
    @Operation(summary = "查看其他用户信息", description = "查看其他用户的公开信息")
    @BusinessLog(value = "查看其他用户信息", params = "userId")
    public YunkeResult<YunkeUserInfoVo> getOtherUserProfile(@Parameter(description = "用户ID") @PathVariable Long userId) {
        YunkeUserInfoVo result = userService.getOtherUserProfile(userId);
        return YunkeResult.success(result);
    }

    /**
     * 系统设置
     */
    @PostMapping("/settings")
    @Operation(summary = "系统设置", description = "更新系统设置")
    @BusinessLog(value = "系统设置", params = "settingKey")
    public YunkeResult<Boolean> updateSystemSettings(
            @Parameter(description = "设置项") @NotBlank @RequestParam String settingKey,
            @Parameter(description = "设置值") @RequestParam String settingValue) {
        boolean result = userService.updateSystemSettings(settingKey, settingValue);
        return YunkeResult.success(result);
    }

    /**
     * 意见反馈
     */
    @PostMapping("/feedback")
    @Operation(summary = "意见反馈", description = "提交意见反馈")
    @BusinessLog(value = "意见反馈", params = "content")
    public YunkeResult<Boolean> submitFeedback(
            @Parameter(description = "反馈内容") @NotBlank @RequestParam String content,
            @Parameter(description = "反馈图片") @RequestParam(required = false) String images,
            @Parameter(description = "联系方式") @RequestParam(required = false) String contact) {
        boolean result = userService.submitFeedback(content, images, contact);
        return YunkeResult.success(result);
    }

    /**
     * 上传头像
     */
    @PostMapping("/uploadAvatar")
    @Operation(summary = "上传头像", description = "上传用户头像")
    @BusinessLog(value = "上传头像", params = "avatarUrl")
    public YunkeResult<Boolean> uploadAvatar(
            @Parameter(description = "头像URL") @NotBlank @RequestParam String avatarUrl) {
        boolean result = userService.uploadAvatar(avatarUrl);
        return YunkeResult.success(result);
    }

    /**
     * 获取用户认证状态
     */
    @GetMapping("/authStatus")
    @Operation(summary = "获取用户认证状态", description = "获取用户认证状态信息")
    @BusinessLog(value = "获取用户认证状态")
    public YunkeResult<Object> getAuthStatus() {
        Object result = userService.getAuthStatus();
        return YunkeResult.success(result);
    }

    /**
     * 获取收藏列表
     */
    @GetMapping("/favoriteList")
    @Operation(summary = "获取收藏列表", description = "获取用户收藏列表")
    @BusinessLog(value = "获取收藏列表")
    public YunkeResult<Page<Object>> getFavoriteList(
            @Parameter(description = "当前页码") @RequestParam(defaultValue = "1") Long current,
            @Parameter(description = "每页大小") @RequestParam(defaultValue = "10") Long size,
            @Parameter(description = "收藏类型") @RequestParam(required = false) Integer type) {
        Page<Object> result = userService.getFavoriteList(current, size, type);
        return YunkeResult.success(result);
    }

    /**
     * 隐私设置
     */
    @PostMapping("/privacySettings")
    @Operation(summary = "隐私设置", description = "更新隐私设置")
    @BusinessLog(value = "隐私设置", params = "settingType")
    public YunkeResult<Boolean> updatePrivacySettings(
            @Parameter(description = "设置类型") @NotBlank @RequestParam String settingType,
            @Parameter(description = "设置值") @RequestParam String settingValue) {
        boolean result = userService.updatePrivacySettings(settingType, settingValue);
        return YunkeResult.success(result);
    }
} 